package main

import (
	"net/http"
	"os"
	"sample/endpoint"
	"sample/service"
	"sample/transport"

	"github.com/go-kit/log"
	"golang.org/x/time/rate"

	kitprometheus "github.com/go-kit/kit/metrics/prometheus"
	httpTransport "github.com/go-kit/kit/transport/http"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// endpoint 使用端点中间件来解决传输域问题，例如断路和速率限制
// service 使用服务中间件来解决业务领域的问题，例如日志记录和检测
func main() {
	logger := log.NewLogfmtLogger(os.Stderr)
	var svc service.IServer
	svc = service.Server{}

	fieldKeys := []string{"method"}
	requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)
	requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duration of requests in microseconds.",
	}, fieldKeys)
	countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "count_result",
		Help:      "The result of each count method.",
	}, []string{}) // no fields here

	svc = service.LoggingMiddleware{Logger: logger, Next: svc}
	svc = service.InstrumentingMiddleware{
		RequestCount:   requestCount,
		RequestLatency: requestLatency,
		CountResult:    countResult,
		Next:           svc,
	}

	hello := endpoint.MakeHelloEndpoint(svc)
	hello = transport.RateLimitterMiddleware(rate.NewLimiter(1, 1))(hello)

	helloServer := httpTransport.NewServer(
		hello,
		transport.HelloRequestDecoder,
		transport.HelloResponseEncoder,
	)

	bye := endpoint.MakeByeEndpoint(svc)
	bye = transport.RateLimitterMiddleware(rate.NewLimiter(1, 1))(bye)
	byeServer := httpTransport.NewServer(
		bye,
		transport.ByeRequestDecoder,
		transport.ByeResponseEncoder,
	)

	http.Handle("/hello", helloServer)
	http.Handle("/bye", byeServer)
	http.Handle("/metrics", promhttp.Handler())

	err := http.ListenAndServe(":8085", nil)
	if err != nil {
		panic(err)
	}
}
